package com.linwen.excise.od.B;

/**
 * @ClassName _编码能力提升计划
 * @Description TODO
 * @Author zero
 * @DATE 2024/4/4 5:48 PM
 * @Version 1.0
 */
public class _编码能力提升计划 {

    /**
     为了提高自己的代码能力，小张制定了 LeetCode 刷题计划，他选中了 LeetCode 题库中的 n 道题，编号从 0 到 n-1，并计划在 m 天内按照题目编号顺序刷完所有的题目（注意，小张不能用多天完成同一题）。AG注释

     在小张刷题计划中，小张需要用 time[i] 的时间完成编号 i 的题目。此外，小张还可以使用场外求助功能，通过询问他的好朋友小杨题目的解法，可以省去该题的做题时间。为了防止“小张刷题计划”变成“小杨刷题计划”，小张每天最多使用一次求助。

     我们定义 m 天中做题时间最多的一天耗时为 T（小杨完成的题目不计入做题总时间）。请你帮小张求出最小的 T是多少。

     示例 1：

     输入：time = [1,2,3,3], m = 2AG注释

     输出：3

     解释：第一天小张完成前三题，其中第三题找小杨帮忙；第二天完成第四题，并且找小杨帮忙。这样做题时间最多的一天花费了 3 的时间，并且这个值是最小的。

     示例 2：

     输入：time = [999,999,999], m = 4AG注释

     输出：0

     解释：在前三天中，小张每天求助小杨一次，这样他可以在三天内完成所有的题目并不花任何时间。


     **/

    public static void main(String[] args) {
        int[] time = {1, 2, 3, 3};
        int m = 2;
        System.out.println(minTime(time, m));

    }

    public static int minTime(int[] time, int m) {
        if (m > time.length) {// 一天一题且求助，花费0
            return 0;
        }
        int min = 0;
        int max = 0;
        for (int i = 0; i < time.length; i++) {
            max += time[i];
        }
        while (min < max) {
            int mid = min + (max - min) / 2;
            if (check(time, m, mid)) {
                max = mid;
            } else {
                min = mid + 1;
            }
        }
        return min;
    }

    private static boolean check(int[] time, int m, int mid) {
        int helpCount = 0;
        int days = 0;
        int max = time[0];
        int canCost = mid;
        for (int i = 0; i < time.length;) {
            max = Math.max(max, time[i]);
            if (canCost >= time[i]) {// 可以刷题
                canCost -= time[i];
                i++;
            } else { // 时间不够了，可能需要求助
                if (helpCount == 0) { // 求助次数还没用
                    canCost += max;
                    helpCount++;
                    if (canCost >= time[i]) {// 找到最大的那个时间求助
                        canCost -= time[i];
                        i++;
                    } else {// 只能明天了
                        helpCount = 0;
                        canCost = mid;
                        max = time[i];
                        days++;
                        if (days >= m) {
                            return false;
                        }
                    }
                } else {// 无法求助，只能下一天再做
                    helpCount = 0;
                    canCost = mid;
                    max = time[i];
                    days++;
                    if (days >= m) {
                        return false;
                    }
                }
            }
        }
        return true;
    }
}
